<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html lang="zh" xml:lang="zh" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<head>
<META http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Guideline: 预订关联</title>
<meta name="uma.type" content="Guideline">
<meta name="uma.name" content="subscribe-association">
<meta name="uma.presentationName" content="预订关联">
<meta name="element_type" content="other">
<meta name="filetype" content="description">
<meta name="role" content="">
<link rel="StyleSheet" href="./../../../css/default.css" type="text/css">
<script src="./../../../scripts/ContentPageResource.js" type="text/javascript" language="JavaScript"></script><script src="./../../../scripts/ContentPageSection.js" type="text/javascript" language="JavaScript"></script><script src="./../../../scripts/ContentPageSubSection.js" type="text/javascript" language="JavaScript"></script><script src="./../../../scripts/ContentPageToolbar.js" type="text/javascript" language="JavaScript"></script><script src="./../../../scripts/contentPage.js" type="text/javascript" language="JavaScript"></script><script type="text/javascript" language="JavaScript">
					var backPath = './../../../';
					var imgPath = './../../../images/';
					var nodeInfo=null;
					contentPage.preload(imgPath, backPath, nodeInfo,  '', false, false, false);
				</script>
</head>
<body>
<div id="breadcrumbs"></div>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
<tr>
<td valign="top"><a name="Top"></a>
<div id="page-guid" value="1.401846671640991E-305"></div>
<table border="0" cellspacing="0" cellpadding="0" width="100%">
<tr>
<td class="pageTitle" nowrap="true">Guideline: 预订关联</td><td width="100%">
<div align="right" id="contentPageToolbar"></div>
</td><td width="100%" class="expandCollapseLink" align="right"><a name="mainIndex" href="./../../../index.htm"></a><script language="JavaScript" type="text/javascript" src="./../../../scripts/treebrowser.js"></script></td>
</tr>
</table>
<table width="100%" border="0" cellpadding="0" cellspacing="0">
<tr>
<td class="pageTitleSeparator"><img src="./../../../images/shim.gif" alt="" title="" height="1"></td>
</tr>
</table>
<div class="overview">
<table width="97%" border="0" cellspacing="0" cellpadding="0">
<tr>
<td width="50"><img src="./../../../images/guidance.gif" alt="" title=""></td><td>
<table class="overviewTable" border="0" cellspacing="0" cellpadding="0">
<tr>
<td valign="top">预定关联指定当关联实体对象中发生特定事件时，必须通知对象。本指南说明如何使用此关系。</td>
</tr>
</table>
</td>
</tr>
</table>
</div>
<div class="sectionHeading">Relationships</div>
<div class="sectionContent">
<table class="sectionTable" border="0" cellspacing="0" cellpadding="0">
<tr valign="top">
<th class="sectionTableHeading" scope="row">Related Elements</th><td class="sectionTableCell">
<ul>
<li>
<a href="./../../../rup/domains/analysis_and_design_BD3BBB1D.html" guid="_kjFBYN7HEdm8G6yT7-Wdqw">分析与设计</a>
</li>
<li>
<a href="./../../../rup/roles/rup_capsule_designer_F3E66EDF.html" guid="{86253FE7-0036-4D14-8BD7-C18CE86A5E14}">封装体设计员</a>
</li>
<li>
<a href="./../../../rup/tasks/class_design_98F20FF9.html" guid="{27AE0601-2E95-4A6A-8EB3-0A4BA8E5626B}">类设计</a>
</li>
<li>
<a href="./../../../rup/workproducts/rup_design_model_2830034D.html" guid="{8CDAEAD4-5E84-4F50-87FD-3240ED047DE7}">设计模型</a>
</li>
<li>
<a href="./../../../rup/roles/rup_designer_BA8DE74E.html" guid="{DB21F5EF-810B-4994-B120-79FA8774FA9D}">设计人员</a>
</li>
</ul>
</td>
</tr>
</table>
</div>
<div class="sectionHeading">Main Description</div>
<div class="sectionContent">
<table class="sectionTable" border="0" cellspacing="0" cellpadding="0">
<tr valign="top">
<td class="sectionTableSingleCell"><a id="Top" name="Top"></a><a key="预订关联（subscribe-association）" text="指南" name="XE_subscribe-association__guidelines_for" id="XE_subscribe-association__guidelines_for" class="index"></a> 
<h3>
    <a id="Explanation" name="Explanation">说明</a>
</h3>
<p>
    在某些情况下，某个对象是由在另一对象中发生的特定事件来决定的。如果该事件是在边界对象或控制对象中发生的，那么该对象仅告知另一对象所发生的事件。但是，如果事件是在实体对象中发生的，情况就有些不同了。如果没有特别要求实体对象告知其他对象所发生的事件，它可能就不会这样做。
</p>
<p class="exampleheading">
    示例
</p>
<p class="example">
    假设在通过转帐从银行帐户中取款的可能情况下对系统进行了建模。如果所进行的提款造成帐户上出现负差额，则必须立即编写一条通知并发送给客户。是否通知客户与作为实体对象来建模的帐户无关。反之，边界对象应通知客户。
</p>
<p>
    在上例中，边界对象必须重复地对实体对象提出问题“我所期待的事件发生过了吗？” 要明确情况并将实现详细信息一直延迟到设计阶段，可使用一种特殊关联来表达该意图，该关联名为“预订关联”。
</p>
<p>
    预订关联将任意类型的对象和实体对象关联起来，表示：当实体对象中发生特定事件时，将通知相关联的对象。建议您仅使用关联来关联实体对象，因为是实体对象的被动性引发了对关联的需要。另一方面，允许接口对象和控制对象发起通信。因此，无需通过“预订”，而可通过其他方式来履行其职责。
</p>
<p align="center">
    <img height="162" alt="UML 图如下所述。" src="./../../../rup/guidances/guidelines/resources/sbscr001.gif" width="208" />
</p>
<p class="picturetext">
    预订关联将任意类型的对象与实体对象关联起来。当相关联的实体对象中发生特定事件时，将通知关联的该对象。
</p>
<p>
    注意，关联的方向显示只有预订对象知道两个对象之间的关系。对关联的描述完全包括在预定对象中。反过来，相关联的对象实体是以常规方式来定义的，并没有考虑到其他对象也有可能对该对象的任务感兴趣。这还意味着，可在不改变所预订的对象的情况下，对模型添加或删除预订方对象。
</p>
<p>
    对预订关联分配了多重性，表示关联方对象可同时关联多少个目标对象实例。随后描述了关于关联的一个或多个条件，这些条件表示为通知关联方对象而必须发生的情况。该事件可能是关联值或属性值的更改，或是操作评估（某些部分）的更改。事件发生后，将向预订方对象通知该情况。注意，将不传送关于事件任何结果的任何信息，仅传送事件已发生这一事实。如果关联方对象对事件发生后实体对象的生成状态感兴趣，它必须按常规方式与实体对象进行交互。这意味着两者之间还需要有链接。
</p>
<p class="exampleheading">
    示例
</p>
<p class="example">
    在“仓库处理系统”中，必须对托板进行抽样调查，以估量其寿命。因此，每第一百次将托板从仓库的一处移动到另一处时，就要在特定的测试站对托板进行检查。这是通过从控制类“托板抽样调查者”到实体类“托板”的预订关联来建模的。“托板”的每个实例均使用计数器属性来计算托板移动的次数。托板经过一百次移动后，由于预订关联的条件，将通知“托板抽样调查者”。然后，“托板抽样调查者”创建一个特定“任务”，该任务将托板传送到测试站。“托板抽样调查者”与“托板”之间无需任何链接，但是它与“任务”之间必须存在一个链接才能启动任务。
</p>
<p align="center">
    <img height="160" alt="附带文本中描述的图。" src="./../../../rup/guidances/guidelines/resources/sbscr002.gif" width="279" />
</p>
<p class="picturetext">
    托板经过一百次移动后，“托板抽样调查者”将创建一个新“任务”。
</p>
<p>
    预订关联的条件应根据抽象特征来表示，而不是根据该关联的特定属性或操作。这样，关联方对象得以保持对所关联实体对象的内容（将会更改）的独立性。
</p>
<p>
    预订关联并不总是关联两个对象实例。从类到实例的元关系也是有效的。这在下面几小节中有所描述。也存在预订关联将某一对象的类关联的情况，例如，如果特定事件恰恰是该类的实例化。
</p>
<h3>
    <a id="Usage" name="Usage">用法</a>
</h3>
<h4>
    <a id="Subscribe-associations from Boundary Classes" name="Subscribe-associations from Boundary Classes">边界类的预订关联</a>
</h4>
<p>
    有时，如果事件发生在实体对象中，则有必要通知边界类。这将调用<b>预订关联</b>。
</p>
<p class="exampleheading">
    示例
</p>
<p class="example">
    考虑通过转帐方式从银行帐户提款。在此，对实体对象“帐户”执行操作的是控制对象“转帐处理程序”。如果“帐户”的余额为负，边界类“通知编写员”将向客户发送已准备好的通知。因此，该对象与“帐户”之间存在<b>预订关联</b>。规定的条件是余额为负。一旦该事件发生，则立即告知“通知编写员”。由于“通知编写员”的实例要不断注意“帐户”实例中的透支情况，所以这个特定的<b>预订关联</b>是实例关联。
</p>
<p>
    如果客户只接收到有关他的余额很低的信息，这就足够了。但是，如果还应告知客户余额低到<b>何种程度</b>，则“通知编写员”还必须对“帐户”执行操作才能知道确切的数额。要实现该操作，“通知编写员”与“帐户”之间必须存在链接。
</p>
<p align="center">
    <img height="137" alt="附带文本中描述的图。" src="./../../../rup/guidances/guidelines/resources/sbscr005.gif" width="367" />
</p>
<p class="picturetext">
    边界类“通知编写员”预订了实体对象“帐户”中余额降到某一程度以下这一事件。如果“通知编写员”还需要知道赤字的确切金额，则它与“帐户”之间必须存在链接。
</p>
<p>
    边界类的元关联的示例为：实体对象中的某个事件导致生成一个新窗口，且要向用户展示该窗口。之后，某一接口对象类预订该实体对象的实例。
</p>
<h4>
    <a id="Subscribe-associations from Entity Classes" name="Subscribe-associations from Entity Classes">实体类的预订关联</a>
</h4>
<p class="exampleheading">
    示例
</p>
<p class="example">
    在处理网络的系统中，存在作为网络节点运作的多个站，且存在使站与站相互连接的线路。每个站均通过几条线路与其他站连接。站的容量取决于运作的线路的数目。如果有超过 80% 的线路处于运作状态，站的容量就高；如果只有不到 20%
    的线路处于运作状态，站的容量就低；两者之间的则为中等容量。在系统模型中有两个实体对象，“站”和“线路”，两者之间存在<b>预订关联</b>。关联条件是：当“线路”状态（启用或禁用）发生更改时，应通知“站”。
</p>
<p class="example">
    进而言之，如果站的容量降低，将通知预订“站”的控制对象。这在下文中有所描述，该示例也将在下文中继续阐述。
</p>
<p align="center">
    <img height="56" alt="附带文本中描述的图。" src="./../../../rup/guidances/guidelines/resources/sbscr003.gif" width="246" />
</p>
<p class="picturetext">
    一旦“线路”的某一实例发生状态更改，则立即通知“站”实例。
</p>
<p>
    实体类之间的<b>预订关联</b>几乎总是实例关联，这是因为通常涉及已存在的实例。
    但是，可能存在这样的情况：当所关联的实体对象中发生指定的事件时，则创建预订方实体对象的实例。在这样的情况下，关联从一个类转到一个实例，即，这是一个元关联。还可设想：特定实体对象的某一实例希望知道何时创建另一实体对象的新实例。
</p>
<h4>
    <a id="Subscribe-associations from Control Classes" name="Subscribe-associations from Control Classes">控制类的预订关联</a>
</h4>
<p class="exampleheading">
    示例
</p>
<p class="example">
    在上例中，实体对象“站”与实体对象“线路”之间存在<b>预订关联</b>。因此，每当“线路”实例的状态发生更改时，都将通知“站”。这种状态更改将改变“站”的容量。如果容量降低，即只有不到 20%
    的线路处于运作状态，系统必须在网络中通过合适的新方式使该站无效。当然，这不是“站”的任务，但必须由控制对象“站管理员”来执行，后者与“站”的每个实例之间都存在预订关联。
</p>
<p align="center">
    <img height="65" alt="附带文本中描述的图。" src="./../../../rup/guidances/guidelines/resources/sbscr004.gif" width="406" />
</p>
<p class="picturetext">
    控制对象“站管理员”预订实体对象“站”，后者反过来预订实体对象“线路”。
</p>
<p>
    更为常见的是，控制对象的<b>预订关联</b>可能是从类到实例，反之亦然，也就是说，这是元关联。通常，直到事件真正发生后，才创建控制对象的实例，它将涉及到实体对象中发生的事件。但是还可设想：某个控制对象的实例希望知道何时创建特定实体对象的新实例。因此，在少数情况下，<b>预订关联</b>可能是实例关联。
</p>
<p class="exampleheading">
    示例
</p>
<p class="example">
    在上例中，从“站管理员”到“站”的<b>预订关联</b>具有元关联的特征，也就是说，当“站”的容量降低时，类“站管理员”将得到通知。“站管理员”接收到该消息后，将创建一个涉及该事件的实例。
</p><br />
<br /></td>
</tr>
</table>
</div>
<table class="copyright" border="0" cellspacing="0" cellpadding="0">
<tr>
<td class="copyright">Copyright &copy; 2008 版权所有 东软集团股份有限公司&nbsp; 联系邮箱:<a href="mailto:tcoe@neusoft.com">tcoe@neusoft.com</a></td>
</tr>
</table>
</td>
</tr>
</table>
</body>
<script type="text/javascript" language="JavaScript">
				contentPage.onload();
			</script>
</html>
